﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WenSkin.Controls;

public class ConsoleWriteLine : Control
{
    private MessageCollection items;


    #region 公有属性

    [Category("WenAuto"), Description("是否显示序号"), DefaultValue(false)]
    public bool ShowLine { get; set; }
    #endregion


    public ConsoleWriteLine()
    {
        SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true);
        UpdateStyles();

        Controls.Add(vScrollBar);
        vScrollBar.ValueChanged += VScrollBar_ValueChanged;
        MouseWheel += ConsoleWriteLine_MouseWheel;
        MouseEnter += ConsoleWriteLine_MouseEnter;
    }

    private void ConsoleWriteLine_MouseEnter(object sender, EventArgs e)
    {
        Select();
    }
    private void ConsoleWriteLine_MouseWheel(object sender, MouseEventArgs e)
    {
        if (e.Delta < 0)
        {
            var v = vScrollBar.Value + 1;
            if (vScrollBar.Maximum >= v)
                vScrollBar.Value++;
        }
        else
        {
            var v = vScrollBar.Value - 1;
            if (vScrollBar.Minimum <= v)
                vScrollBar.Value--;
        }
    }


    private void VScrollBar_ValueChanged(object sender, EventArgs e)
    {
        Invalidate(true);
    }

    private void SetVS()
    {
        var count = (int)Math.Floor((float)Height / 20);
        if (Items.Count >= count)
        {
            vScrollBar.Maximum = Items.Count - count;
            vScrollBar.Value = Items.Count - count;
        }
        else
        {
            vScrollBar.Maximum = 0;
            vScrollBar.Value = 0;
        }
    }

    private VScrollBar vScrollBar = new VScrollBar() { Dock = DockStyle.Right, Maximum = 0, Value = 0, LargeChange = 1 };

    public MessageCollection Items => items ??= new MessageCollection(this);


    public static StringFormat StringConters { get; set; }
    = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap)
    {
        LineAlignment = StringAlignment.Center,
        Trimming = StringTrimming.EllipsisCharacter
    };

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        g.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高，即消除锯齿
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.CompositingQuality = CompositingQuality.HighQuality;


        g.DrawRectangle(Pens.Black, new Rectangle(0, 0, Width - vScrollBar.Width - 1, Height - 1));


        var count = (int)Math.Ceiling((float)Height / 20);

        var cuowei = count * 20 - Height;


        if (vScrollBar.Value == 0)
        {
            cuowei = 0;
        }

        if (count > Items.Count)
        {
            count = Items.Count;
        }


        for (int i = 0; i < count; i++)
        {
            var line = (vScrollBar.Value > 0 ? vScrollBar.Value - 1 : 0) + i;
            var item = Items[line];

            var rec = new RectangleF(3, i * 20 - cuowei, Width - vScrollBar.Width - 6, 20);


            var text = $"{(ShowLine ? line + 1 + ". " : "")}{item.DateTime:HH:mm:ss} {item.Text}";
            g.DrawString(text, Font, new SolidBrush(item.Color), rec, StringConters);
        }
    }


    public class MessageCollection : List<MessageItem>
    {
        private ConsoleWriteLine owner;

        public MessageCollection(ConsoleWriteLine owner)
        {
            this.owner = owner;
        }

        public void Add(string text) => Add(text, Color.Black);
        public void Add(string text, Color color)
        {
            Add(new MessageItem(text, color));
            ReOwner();
        }
        public new void Clear()
        {
            base.Clear();
            ReOwner();
        }

        private void ReOwner()
        {
            owner.Invalidate();
            owner.Invoke(owner.SetVS);
        }
    }

    public class MessageItem
    {
        public MessageItem(string text, Color color)
        {
            Text = text;
            Color = color;
        }
        public DateTime DateTime { get; set; } = DateTime.Now;
        public string Text { get; set; } = "";
        public Color Color { get; set; } = Color.Black;
    }
}
